/*
 *
 *  Created: 2/14/2014 2:34:20 PM
 *   Author: swinney2
 */ 


/* To tell if a number is divisible by 3 or 5 you have to divide the number by three and at
each interval check and see if the remainder is 0 or negative. If its greater then 
0 keep subtracting by 3 or 5 until it passes that test. Once its found that its
divisible store in its respectable register. 
*/

.INCLUDE "M328PDEF.INC" //library for atmega328 chip
.MACRO INITSTACK //creating macro
                LDI     R16, HIGH(RAMEND) //initialize the loop high
                OUT     SPH, R16 //set stack pointer high
                LDI     R16, LOW(RAMEND) //initialize the loop low
                OUT     SPL, R16 //set stack pointer low
        .ENDMACRO


INITSTACK
                LDI     R20, 2 //Adding two to given register
                LDI     R17, 0; Total Numbers Generate
                LDI     R19, 5 //This is used for the counter
                LDI     R18, 32 //Copy of the Starting Value 
RAND_LOOP1:
                LDI     R22, 8 //1st Value to add to New Number
                LDI     R23, 3 //2nd Value to subtract to New Number
                ADD     R18, R22 //Add 9 to current number
                PUSH    R18 //push number onto stack
                SUB     R18, R23 //Subtract 4 from the current number
                PUSH    R18 //Push number onto stack                ADD     R17, R20 //add two to total numbers generated
                SUBI    R19, 1 //decrement loop counter
                BRNE    RAND_LOOP1 //branch if not equal
                
                LDI     R19, 5 //This is used for the counter 
RAND_LOOP2:
                LDI     R22, 12 //1st Value to add to New Number
                LDI     R23, 4 //2nd Value to add to New Number
                ADD     R18, R22 //Add 7 to current number
                PUSH    R18 //push number onto stack
                SUB     R18, R23 //Subtract 4 from the current number
                PUSH    R18 //Push number onto stack
                ADD     R17, R20 //add two to total numbers generated
                SUBI    R19, 1 //decrement loop counter
                BRNE    RAND_LOOP2 //branch if not equal

			    LDI     R16, 3;//preloads 3 back into the registeR
                LDI     R19, 5 //preloads 5 back into the register
				LDI		R23, 0 //clears the r23 register
				LDI		R20, 0 //clears the r20 register (contains the sum of divis by 3 numbers)
				LDI		R22, 0 //clears the r20 register (contains the sum of divis by 5 numbers)
				LDI		R26, 1 //Loading a 1 in this register to be added to the higher result registers when a numbers divisible
				ADD		R17, R26 // modify counter to add one more to pop numbers
				ADD		R17, R26 // modify counter to add one more to pop numbers
			
POP_NEW_NUM:
				POP		R18 //pops next number to be evaluated
				SUBI    R17, 1 //decrements 1 from the count to only check 20 for numbers only
                BREQ    DONE_CHECK //if its reached 0 its done and to exit out
                MOV     R27, R18; //REGISTER TO CHECK IF DIVIS BY 3
                MOV     R25, R18; //REGISTER TO CHECK IF DIVIS BY 5
				JMP		DIVIS_LOOP3 //Jump to label to start testing divisibility

DIVIS_LOOP5:
                SUB     R25, R19 //subtracting 5 here to test divisibility by 5
 				BRPL    DIVIS_LOOP5 //branch if n = 0, POSITIVE NUM
				ADD		R25, R19 //add back the 3 we subtracted to test if the content in the reg is 0
				CPI		R25, 0; // compare register if equal to 0
				BRNE	POP_NEW_NUM //Jumps to label to select another number
				JMP		ADD_DIVIS_5 //if it is divis add then to lower register


DIVIS_LOOP3: 
				SUB		R27, R16; //subtracting 3 here to test divisibility by 3
 				BRPL    DIVIS_LOOP3 //branch if n = 0, POSITIVE NUM
				ADD		R27, R16 //add back the 3 we subtracted to test if the content in the reg is 0
				CPI		R27, 0 // compare register if equal to 0
				BRNE	DIVIS_LOOP5 //if not divis by 3, jmp to check if its divis by 5 
				JMP		ADD_DIVIS_3	//if it is divis add then to lower register

ADJUST_BITS5:
				ADD		R23, R26 //ADDING A 1 TO THE UPPER REGISTER, R23
				JMP		POP_NEW_NUM //Jumps to label to select another number

ADJUST_BITS3:
				ADD		R20, R26 //ADDING A 1 TO THE UPPER REGISTER, R20
				JMP		DIVIS_LOOP5 //jump to testing divisibility by 5 
	             
ADD_DIVIS_3:
				ADD		R21, R18 //adding number thats divisible by 3 to lower register R21
				BRCS	ADJUST_BITS3 //jump to adjust bits if theres a carry after adding to R21
				JMP		DIVIS_LOOP5 //jump to start testing divisibility by 5

ADD_DIVIS_5:	
				ADD		R24, R18 //adding number thats divisible by 5 to lower register R24
				BRCS	ADJUST_BITS5 //jump to adjust bits if theres a carry after adding to R24
				JMP		POP_NEW_NUM //Jumps to label to select another number

DONE_CHECK:
				JMP DONE_CHECK //Ends the program